; Program to input a message and echo it in lower case
; Author:  R. Detmer
; Date:    6/98

.386
.MODEL FLAT

ExitProcess PROTO NEAR32 stdcall, dwExitCode:DWORD

GetStdHandle PROTO NEAR32 stdcall,
    nStdHandle:DWORD

ReadFile PROTO NEAR32 stdcall,
    hFile:DWORD, lpBuffer:NEAR32, nNumberOfCharsToRead:DWORD,
    lpNumberOfBytesRead:NEAR32, lpOverlapped:NEAR32

WriteFile PROTO NEAR32 stdcall,
    hFile:DWORD, lpBuffer:NEAR32, nNumberOfCharsToWrite:DWORD,
    lpNumberOfBytesWritten:NEAR32, lpOverlapped:NEAR32

STD_INPUT  EQU -10
STD_OUTPUT EQU -11

.STACK
.DATA

prompt  BYTE    "String to convert? "
CrLf    BYTE    0ah, 0dh
StrIn   BYTE    80 DUP (?)
read    DWORD   ?
written DWORD   ?
hStdIn  DWORD   ?
hStdOut DWORD   ?

.CODE  
_start: 
        INVOKE GetStdHandle,    ; get handle for console output
          STD_OUTPUT
        mov    hStdOut, eax

        INVOKE WriteFile,
          hStdOut,              ; file handle for screen
          NEAR32 PTR prompt,    ; address of prompt
          19,                   ; length of prompt
          NEAR32 PTR written,   ; bytes written
          0                     ; overlapped mode

        INVOKE GetStdHandle,    ; get handle for console input
          STD_INPUT
        mov    hStdIn, eax

        INVOKE ReadFile,
          hStdIn,               ; file handle for keyboard
          NEAR32 PTR StrIn,     ; address of string
          80,                   ; maximum number to read
          NEAR32 PTR read,      ; bytes read
          0                     ; overlapped mode

        mov    ecx, read        ; set up loop to convert
        lea    ebx, StrIn       ; starting address
forCh:  cmp    BYTE PTR [ebx], 'A'  ; char < 'A' ?
        jl     endIfUpper       ; skip if so
        cmp    BYTE PTR [ebx], 'Z'  ; char > 'Z' ?
        jg     endIfUpper       ; skip if so
        add    BYTE PTR [ebx], 'a' - 'A'  ; convert to lower
endIfUpper:
        inc    ebx              ; point at next character
        loop   forCh            ; repeat

        mov    ecx, read        ; get length to write
        add    ecx, 2           ; for leading CR and LF
        
        INVOKE WriteFile,
          hStdOut,              ; file handle for screen
          NEAR32 PTR crLf,      ; start with
          ecx,                  ; length of output
          NEAR32 PTR written,   ; bytes written
          0                     ; overlapped mode
                                                  
        INVOKE  ExitProcess, 0  ; exit with return code 0

PUBLIC _start
END

